package com.hongye.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import com.hongye.app.model.OrderInfoModel;
import com.hongye.app.model.PaymentModel;

/**
 * 微信相关
 * @author Administrator
 *
 */
public class WeixinUtils {
	
	public static Logger log = Logger.getLogger(WeixinUtils.class);
	public static final String STRING = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
	public static final String mch_id = "1439522502"; //微信支付商户号
	public static final String appid = "wx45f39c3f3d19aca7"; //应用APPID
	public static final String sign_type = "MD5"; //签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
	public static final String trade_type = "APP"; //签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
	public static final String key = "6IX8KH21RR0ZQ2PI7ROLQ73WTZOX0CGO"; //签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
	public static final String notify_url = "http://120.27.117.192/rbg/weixin/notify_url"; //微信支付异步通知回调地址
	public static final String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; //统一下单接口链接 
	public static final String orderquery_url = "https://api.mch.weixin.qq.com/pay/orderquery"; //查询订单接口链接 
	public static final String refund_url = "https://api.mch.weixin.qq.com/secapi/pay/refund"; //申请退款接口链接 
	
	
	public WeixinUtils() {
		
	}
	
	/**
	 * 申请退款
	 * @author lifuqiang
	 * 2017-2-21
	 * @param out_trade_no:订单号
	 * @param total_fee：总金额
	 * @param refund_fee：退款金额
	 * @throws Exception 
	 */
	public static boolean refund(String out_trade_no, double total_fee, double refund_fee){
		Map<String, Object> sParaTemp = new HashMap<String, Object>();
		sParaTemp.put("appid", appid);//应用ID
		sParaTemp.put("mch_id", mch_id);//商户号
		sParaTemp.put("nonce_str", getRandomString(32));//随机字符串
		sParaTemp.put("out_trade_no", out_trade_no);//商户订单号
		sParaTemp.put("out_refund_no", Utils.getOrderSN());//商户退款单号
		sParaTemp.put("total_fee", (int)Utils.muti(total_fee, 100));//总金额
		sParaTemp.put("refund_fee", (int)Utils.muti(refund_fee, 100));//退款金额
		sParaTemp.put("op_user_id", mch_id);//操作员帐号, 默认为商户号
		String sign = WeixinUtils.formatQueryParaMap(sParaTemp);
		sParaTemp.put("sign", sign);//签名
		boolean boo = false;
		try {
			String resultxml = HttpUtils.doRefund(refund_url, getRequestXml(sParaTemp));
			if(resultxml !=  null){
				Map<String, Object> result = doXMLParse(resultxml);
				if(log.isInfoEnabled()){log.info("weixin result="+result);}
				if(null != result && result.get("return_code").equals("SUCCESS") && result.get("result_code").equals("SUCCESS")){
					boo = true;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return boo;
	}
	
	/**
	 * 查询订单 接口
	 * @author liushaomin
	 * 2017年2月21日
	 * @param transaction_id 微信订单号
	 * @return
	 */
	public static Map<String, Object> query(String transaction_id) {
		Map<String, Object> sParaTemp = new HashMap<String, Object>();
		sParaTemp.put("appid", WeixinUtils.appid);
		sParaTemp.put("mch_id", WeixinUtils.mch_id);
		sParaTemp.put("transaction_id", transaction_id);
		sParaTemp.put("nonce_str", WeixinUtils.getRandomString(32));
		sParaTemp.put("sign", WeixinUtils.formatQueryParaMap(sParaTemp));
		String resultxml = HttpUtils.sendPostXml(WeixinUtils.orderquery_url, WeixinUtils.getRequestXml(sParaTemp));
		Map<String, Object> result = WeixinUtils.doXMLParse(resultxml);
		if(log.isInfoEnabled()){log.info("weixin query result="+result);}
		return result;
	}
	
	/**
	 *  随机生成字符串
	 * 	微信调用
	 * @author lifuqiang
	 * 2017-2-15
	 * @param length
	 * @return
	 */
	public static String getRandomString(int length){
	    StringBuffer buffer = new StringBuffer();
	    int len = STRING.length();
	    for (int i = 0; i < length; i++) {
	    	buffer.append(STRING.charAt(Utils.getRandom(len-1)));
	    }
	    return buffer.toString();
	}
	
	/**
	 * 将参数按照字段名的 ASCII 码从小到大排序（字典序）使用 URL 键值
	 * 对的格式（即key1=value1&key2=value2…）拼接成字符串
	 * 在stringA最后拼接上key得到stringSignTemp字符串，并对stringSignTemp进行MD5运算，再将得到的字符串所有字符转换为大写，得到sign值signValue。
	 * @author lifuqiang
	 * 2017-2-15
	 * @param paraMap	参数
	 * @param isURLEncode	是否对所有Value进行URLEncod转码
	 * @return
	 */
	public static String formatQueryParaMap(Map<String, Object> paraMap) {
		StringBuilder buil = new StringBuilder();
        List<String> keys = new ArrayList<String>(paraMap.keySet());
        Collections.sort(keys);
        for (int i = 0; i < keys.size(); i++) {
			 String key = keys.get(i);
			 Object val = paraMap.get(key);
             if (null != val && !"".equals(val) && !"sign".equals(key) && !"key".equals(key)){
            	 buil.append(key + "=" + val + "&");
             }
         }
		 buil.append("key=" + key);
		return Utils.strToMD5(buil.toString()).toUpperCase();
	}
	
	/**
	 * 封装xml参数 
	 * @author liushaomin
	 * 2017年2月23日
	 * @param parameters
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static String getRequestXml(Map<String, Object> parameters){
        StringBuffer buffer = new StringBuffer();
        buffer.append("<xml>");
        Set<?> es = parameters.entrySet();
        Iterator<?> it = es.iterator();
        while(it.hasNext()) {
		Map.Entry entry = (Map.Entry)it.next();
          String k = entry.getKey().toString();
          String v = entry.getValue().toString();
          buffer.append("<" + k + ">" + v + "</" + k + ">");
        }
        buffer.append("</xml>");
        return buffer.toString();
    }  
	
	/**
	 * 返回给微信异步回调的参数封装 xml
	 * @author liushaomin
	 * 2017年2月17日
	 * @param return_code
	 * @param return_msg
	 * @return
	 */
	public static String backWeixin(String return_code, String return_msg){
		 StringBuffer bf = new StringBuffer();
         bf.append("<xml>");
         
         bf.append("<return_code>");
         bf.append(return_code);
         bf.append("</return_code>"); 
         
         bf.append("<return_msg>");
         bf.append(return_msg);
         bf.append("</return_msg>");
         
         bf.append("</xml>");
         return bf.toString();
	}
	
	/**
	 * 解析xml,返回第一级元素键值对。如果第一级元素有子节点，则此节点的值是子节点的xml数据。
	 * @author liushaomin
	 * 2017年2月16日
	 * @param strxml
	 * @return
	 * @throws JDOMException
	 * @throws IOException
	 */
	public static Map<String, Object> doXMLParse(String strxml){
		strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
		if(null == strxml || "".equals(strxml)) {
			return null;
		}
		Map<String, Object> m = new HashMap<String, Object>();
		try {
			InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
			SAXBuilder builder = new SAXBuilder();
			Document doc;
				doc = builder.build(in);
				Element root = doc.getRootElement();
				List<?> list = root.getChildren();
				Iterator<?> it = list.iterator();
				while(it.hasNext()) {
					Element e = (Element) it.next();
					String k = e.getName();
					String v = "";
					List<?> children = e.getChildren();
					if(children.isEmpty()) {
						v = e.getTextNormalize();
					} else {
						v = getChildrenText(children);
					}
					m.put(k, v);
				}
				//关闭流
				in.close();
		} catch (UnsupportedEncodingException e2) {
			e2.printStackTrace();
		} catch (JDOMException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		return m;
	}
	
	/**
	 * 获取子结点的xml
	 * @author liushaomin
	 * 2017年2月16日
	 * @param children
	 * @return
	 */
	public static String getChildrenText(List<?> children) {
		StringBuffer buff = new StringBuffer();
		if(!children.isEmpty()) {
			Iterator<?> it = children.iterator();
			while(it.hasNext()) {
				Element e = (Element) it.next();
				String name = e.getName();
				String value = e.getTextNormalize();
				List<?> list = e.getChildren();
				buff.append("<" + name + ">");
				if(!list.isEmpty()) {
					buff.append(getChildrenText(list));
				}
				buff.append(value);
				buff.append("</" + name + ">");
			}
		}
		return buff.toString();
	}
	
	/**
	 * 更新订单（多个订单支付）
	 * @author liushaomin
	 * 2017年2月22日
	 * @param orderids
	 * @param para
	 * transaction_id 微信交易号, openid 微信用户表示
	 */
	public static void UpOrder(String orderids,  Map<String,Object> para){
		List<PaymentModel> payments = PaymentModel.getListByOrderids_Channel(orderids,"weixin");
		for (PaymentModel item : payments) {
			OrderInfoModel.UpdateStatusByOrdersn(item.getStr("ordersn"), "1", para.get("transaction_id").toString());
			item.set("payment_account", para.get("openid")).set("successtime", para.get("time_end")).set("state", 2).update();
			PushUtils.MSG_Single(OrderInfoModel.getSellerByOrdersn(item.getStr("ordersn")), "B01", "您有一个新订单，赶紧去发货吧！");
		}
	}
	
	/**
	 * 更新订单（单个订单支付）
	 * @author liushaomin
	 * 2017年2月22日
	 * @param ordersn
	 * @param para
	 * transaction_id 微信交易号, openid 微信用户表示
	 */
	public static void UpOrder_single(String ordersn,  Map<String,Object> para){
		 PaymentModel payment = PaymentModel.getPaymentByOrderSN_Channel_state(ordersn, "weixin", 0);
		 OrderInfoModel.UpdateStatusByOrdersn(ordersn, "1", para.get("transaction_id").toString());
		 payment.set("payment_account", para.get("openid")).set("successtime", para.get("time_end")).set("state", 2).update();
		 PushUtils.MSG_Single(OrderInfoModel.getSellerByOrdersn(ordersn), "B01", "您有一个新订单，赶紧去发货吧！");
	}
}
